import System.Random
import Data.Time
import Data.Time.Clock.POSIX
import System.IO.Unsafe
import Data.Maybe

--------------------------------------------------------------
--Declaración de tipos e Instanciación de clases
data Palo = Espada | Basto | Oro | Copa deriving (Show,Eq)

data Carta = CartaNula | Carta {numero::Int, palo::Palo, peso::Int}-- deriving (Show)

instance Show (Carta) where
    show CartaNula = "|__|"
    show (Carta num pal pes) = "|"++show num++","++show pal++"|"-- ++"("++show pes++")"

instance Eq (Carta) where
    CartaNula == CartaNula = True
    CartaNula == (Carta n pal pes) = False
    (Carta n pal pes) == CartaNula = False
    (Carta n1 pal1 pes1) == (Carta n2 pal2 pes2) = pes1 == pes2 -- dos cartas son iguales si sus pesos son iguales
    
instance Ord (Carta) where
    CartaNula <= (Carta n pal pes) = True
    (Carta n1 pal1 pes1) <= (Carta n2 pal2 pes2) = pes1 <= pes2 -- una carta es menor que otra si su peso es menor


data Envido = Envido | RealEnvido | FaltaEnvido deriving (Show,Eq)
data Truco = NoTruco | Truco | Retruco | ValeCuatro deriving (Show,Eq)
data Respuesta = NoRespuesta | Quiero | NoQuiero deriving (Show,Eq)
data Jugador = JugadorNulo | Maquina | Humano deriving (Show,Eq)
type Estado = (Jugador,Jugador,Int,([Envido],Jugador),Respuesta,(Truco,Jugador),Respuesta,[(Carta,Carta,Carta)],[Int],[(Carta,Carta,Carta)]) -- (Quien es Mano,Quien Juega,Turno,Envidos Cantados y quien lo cantó,Respuesta al envido,Nivel de Truco y quien lo cantó,Respuesta al truco,Manos de ambos jugadores, Puntos de ambos jugadores,Cartas jugadas)

-- IMPLEMENTACION FUTURA:
--
--  Estado necesita:
--      
--          2 campos Int para los puntos... si llego a 30 termina el juego
--          Lista de Cartas que tiene cada jugador en la mano (o tupla)
--          

-----------------------------------------------------------------
--Funciones Auxiliares
qsort []     = []
qsort (p:xs) = (qsort lesser) ++ [p] ++ (qsort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) xs

primera :: (Carta,Carta,Carta) -> Maybe Carta
primera (CartaNula,_,_) = Nothing
primera (a,_,_) = Just a

segunda :: (Carta,Carta,Carta) -> Maybe Carta
segunda (_,CartaNula,_) = Nothing
segunda (_,b,_) = Just b

tercera :: (Carta,Carta,Carta) -> Maybe Carta
tercera (_,_,CartaNula) = Nothing
tercera (_,_,c) = Just c

cambioJugador :: Jugador -> Jugador
cambioJugador Humano = Maquina
cambioJugador Maquina = Humano

elegirCarta :: Carta -> Carta -> Carta
elegirCarta CartaNula CartaNula = CartaNula
elegirCarta CartaNula c2 = c2
elegirCarta c1 _ = c1

rearmarMano :: (Carta,Carta,Carta) -> (Carta,Carta,Carta) -> (Carta,Carta,Carta)
rearmarMano (m1,m2,m3) (j1,j2,j3)
    | noRepetidas (manoEnOrden) = if (manoCompleta manoEnOrden) then manoEnOrden else (rearmarMano manoEnOrden (j3,j1,j2))
    | otherwise = rearmarMano (m1,m2,m3) (j3,j2,j1)
        where
            manoCompleta (c1,c2,c3) = ((c1 /= CartaNula) && (c2 /= CartaNula) && (c3 /= CartaNula))
            noRepetidas (c1,c2,c3) = ((c1 /= c2) && (c1 /= c3) && (c2 /= c3))
            manoEnOrden = (elegirCarta m1 j1,elegirCarta m2 j2,elegirCarta m3 j3)
-----------------------------------------------------------------
--Pesos, Cartas posibles y Mazo

-- Reglas de Asignación del peso:
-- 1 espada: peso = 16
-- 1 basto: peso = 15
-- 7 espada: peso = 14
-- 7 oro: peso = 13
-- 1 hasta 3, (1 de espada y basto no): pedo = numero + 9 (10 a 12)
-- 4 hasta 12, (7 de oro y espada no): peso = numero - 3 (1 a 9) (8 y 9 salta error pero no me molesta que haya un salto en el peso del 7 al 10)

asignaPeso :: Int -> Palo -> Carta
asignaPeso 1 Espada = (Carta 1 Espada 16)
asignaPeso 1 Basto =  (Carta 1 Basto 15)
asignaPeso 7 Espada = (Carta 7 Espada 14)
asignaPeso 7 Oro = (Carta 7 Oro 13)
asignaPeso num pal 
    | num <= 3 = (Carta num pal (num+9))
    | num > 7 && num < 10 = error ("Carta no válida")
    | otherwise = (Carta num pal (num-3))

palos = [Espada, Basto, Oro, Copa]
numeros = [1..7]++[10..12]

mazo = [(asignaPeso num pal)| num <- numeros , pal <- palos]

------------------------------------------------------------------
--Random y mezclado del mazo

rnd :: StdGen -> Int -> [Int] -> [Int] -- Generador -> cantidad que quiero -> lista para acumular -> resultado
rnd g i x
    | i <= 1 = (newI:x)
    | otherwise = rnd newG (i-1) (newI:x)
        where
            newG = snd (random g :: (Int,StdGen))
            newI = fst (random g :: (Int,StdGen)) `mod` 200
        
shuffle :: [Carta] -> Int -> [Carta]
shuffle [] _ = []
shuffle x 0 = x
shuffle (x:xs) i = shuffle ((take ran xs)++[x]++(drop ran xs)) (i - 1)
    where
        ran = head (rnd (mkStdGen $ time) (1) []) `mod` (length xs -1)
        time = (round (unsafePerformIO getPOSIXTime * 100000) :: Int) `mod` (length xs) --NEGRADA: Transformo IO Int de GetPOSIXTime en INT para poder operar con rnd

-------------------------------------------------------------
        
repartir ::  [Carta] -> [(Carta,Carta,Carta)]
repartir [] = error "No puedo repartir sin cartas"
repartir xs = [(a,b,c)|a<-(take 1 baraja),b<-(take 1 $drop 1 baraja),c<-(take 1 $drop 2 baraja)] ++ [(d,e,f)|d<-(take 1 $drop 3baraja),e<-(take 1 $drop 4 baraja),f<-(take 1 $drop 5 baraja)]
    where
        baraja = shuffle xs 200
        
--------------------------------------------------------------
-- Envido

contarEnvido :: Carta -> Carta -> Int
contarEnvido (Carta n1 p1 _) (Carta n2 p2 _)
    |p1 /= p2 = max (pun n1) (pun n2)
    |p1 == p2 = (pun n1) + (pun n2) + 20
        where
            pun n = if n>=10 then 0 else n
            
envido :: (Carta,Carta,Carta) -> Maybe Int -- Acepta solo manos de 3 cartas y devuelve el mayor de los envidos que tenga envuelto en un Maybe
envido (CartaNula,_,_) = Nothing
envido (_,CartaNula,_) = Nothing
envido (_,_,CartaNula) = Nothing
envido (a,b,c) = Just (maximum [(contarEnvido a b),(contarEnvido a c),(contarEnvido b c)])

--------------------------------------------------------------
manoVacia :: (Carta,Carta,Carta)
manoVacia = (CartaNula,CartaNula,CartaNula)

estadoInicial :: Estado
estadoInicial = (Humano,Humano,1,([],JugadorNulo),NoRespuesta,(NoTruco,JugadorNulo),NoRespuesta,repartir mazo,[0,0],[manoVacia,manoVacia])

motor :: Estado -> Estado
motor (m,j,4,_,_,_,_,_,puntos,jugadas) = (cambioJugador m,cambioJugador j,1,([],JugadorNulo),NoRespuesta,(NoTruco,JugadorNulo),NoRespuesta,repartir mazo,puntos,[manoVacia,manoVacia])

------------------------------

--  Estado = (Mano,Jugador,Turno,[Envido],Respuesta al Envido,Truco,Respuesta al Truco,Manos de ambos jugadores, Puntos de ambos jugadores,Cartas jugadas)
--
--  Mano = True/False
--  Jugador = Humano/Maquina
--  Turno = 1,2,3
--  Envido = NoEnvido,Envido,RealEnvido,FaltaEnvido
--  Truco = NoTruco, Truco, Retruco, ValeCuatro
--  Manos de los jugadores = Lista de 2 tuplas de 3 cartas cada una
--  Puntos = Lista de 2 enteros
--  Cartas jugadas = Lista de 2 tuplas de 3 cartas cada una. Empieza con cartas nulas

-- Motor de juego cambia el estado (y devuelve uno nuevo) a partir de las reglas

------------------------------------------------------------------

cantarEnvido :: Estado -> Envido -> Maybe Estado --lo llamo para cantar algun nivel de envido. Al ser Maybe me permite detectar si hubo un canto erróneo y avisarle al jugador en lugar de que pierda el turno
--
cantarEnvido (_,_,_,_,_,(Retruco,jugT),_,_,_,_) _ = Nothing -- Si se cantó Retruco o ValeCuatro es xq ya cantaron Truco antes y se quiso. No se puede cantar Envido
cantarEnvido (_,_,_,_,_,(ValeCuatro,jugT),_,_,_,_) _ = Nothing
--
cantarEnvido (m,j,1,([],jugE),re,(Truco,jugT),NoRespuesta,cartas,puntos,jugadas) e = Just (m,j,1,([e],j),NoRespuesta,(Truco,jugT),NoRespuesta,cartas,puntos,jugadas) -- Primero está el envido
cantarEnvido (m,j,1,([],jugE),re,(Truco,jugT),r,_,_,_) _ = Nothing -- no puedo cantar envido, canté yo el truco y me lo respondieron
--
cantarEnvido (m,j,1,([],jugE),re,(t,jugT),rt,cartas,puntos,jugadas) e = Just (m,j,1,([e],j),NoRespuesta,(t,jugT),rt,cartas,puntos,jugadas) -- Si no se cantó nada puedo cantar cualquier Envido
--
cantarEnvido (m,j,1,([Envido],jugE),re,(t,jugT),rt,cartas,puntos,jugadas) e = Just (m,j,1,((e:[Envido]),j),NoRespuesta,(t,jugT),rt,cartas,puntos,jugadas) -- Si se cantó Envido una sola vez puedo cantar cualquiera
--
cantarEnvido (m,j,1,((Envido:(Envido:env)),jugE),re,(t,jugT),rt,cartas,puntos,jugadas) Envido = Nothing -- Si se cantó 2 veces Envido no lo puedo volver a cantar
cantarEnvido (m,j,1,((Envido:(Envido:env)),jugE),re,(t,jugT),rt,cartas,puntos,jugadas) e = Just (m,j,1,((e:(Envido:(Envido:env))),j),NoRespuesta,(t,jugE),rt,cartas,puntos,jugadas)
--
cantarEnvido (m,j,1,((RealEnvido:env),jugE),re,(t,jugT),rt,cartas,puntos,jugadas) FaltaEnvido = Just (m,j,1,((FaltaEnvido:(RealEnvido:env)),j),NoRespuesta,(t,jugT),rt,cartas,puntos,jugadas)
cantarEnvido (m,j,1,((RealEnvido:env),juge),re,(t,jugT),rt,cartas,puntos,jugadas) _ = Nothing -- solamente puedo cantar FaltaEnvido si cantaron RealEnvido
--
cantarEnvido (m,j,1,((FaltaEnvido:env),jugE),re,(t,jugT),rt,cartas,puntos,jugadas) _ = Nothing -- si cantaron FaltaEnvido no puedo cantar nada más
--
cantarEnvido (_,_,n,_,_,_,_,_,_,_) _ = Nothing -- si no matcheó hasta ahora quiere decir que no estoy en la primera mano, no puedo cantar envido

responderEnvido :: Estado -> Respuesta -> Maybe Estado
responderEnvido (m,j,turno,([],jugE),re,(truco,jugT),rt,cartas,puntos,jugadas) _ = Nothing -- no puedo responder si no me cantaron
responderEnvido (m,j,turno,(env,jugE),re,(truco,jugT),rt,cartas,puntos,jugadas) NoRespuesta = Nothing
responderEnvido (m,j,turno,(env,jugE),re,(truco,jugT),rt,cartas,puntos,jugadas) res = Just (m,j,turno,(env,jugE),res,(truco,jugT),rt,cartas,puntos,jugadas)

----------------------------------------------------------------------
cantarTruco :: Estado -> Truco -> Maybe Estado -- lo llamo para cantar algun nivel de truco
--
cantarTruco (m,j,turno,([],jugE),re,(NoTruco,jugT),rt,cartas,puntos,jugadas) Truco = Just (m,j,turno,([],jugE),re,(Truco,j),NoRespuesta,cartas,puntos,jugadas) -- si no se cantó envido no hay problema
cantarTruco (m,j,turno,(env,jugE),NoRespuesta,(NoTruco,jugT),rt,cartas,puntos,jugadas) Truco = Nothing -- Primero está el envido
cantarTruco (m,j,turno,(env,jugE),re,(NoTruco,jugT),rt,cartas,puntos,jugadas) Truco = Just (m,j,turno,(env,jugE),re,(Truco,j),NoRespuesta,cartas,puntos,jugadas) -- ya se respondió el envido, puedo cantar
cantarTruco (m,j,turno,(env,jugE),re,(NoTruco,jugT),rt,cartas,puntos,jugadas) _ = Nothing -- no puedo cantar Retruco ni ValeCuatro si no se cantó Truco antes
--
cantarTruco (m,j,turno,(env,jugE),re,(truco,jugT),NoQuiero,cartas,puntos,jugadas) _ = Nothing -- no puedo retrucar si no me quisieron
--
cantarTruco (m,j,turno,([],jugE),re,(Truco,jugT),res,cartas,puntos,jugadas) Retruco = Just (m,j,turno,([],jugE),re,(Retruco,j),NoRespuesta,cartas,puntos,jugadas) -- si no se cantó envido no hay problema
cantarTruco (m,j,turno,(env,jugE),NoRespuesta,(Truco,jugT),res,cartas,puntos,jugadas) Retruco = Nothing -- Primero está el envido
cantarTruco (m,j,turno,(env,jugE),re,(Truco,jugT),res,cartas,puntos,jugadas) Retruco = Just (m,j,turno,(env,jugE),re,(Retruco,j),NoRespuesta,cartas,puntos,jugadas) -- ya se respondió el envido, puedo retrucar
cantarTruco (m,j,turno,(env,jugE),re,(Truco,jugT),res,cartas,puntos,jugadas) _ = Nothing
--
cantarTruco (m,j,turno,([],jugE),re,(Retruco,jugT),res,cartas,puntos,jugadas) ValeCuatro = Just (m,j,turno,([],jugE),re,(ValeCuatro,j),NoRespuesta,cartas,puntos,jugadas) -- si no se cantó envido no hay problema
cantarTruco (m,j,turno,(env,jugE),NoRespuesta,(Retruco,jugT),res,cartas,puntos,jugadas) ValeCuatro = Nothing -- Primero está el envido
cantarTruco (m,j,turno,(env,jugE),re,(Retruco,jugT),res,cartas,puntos,jugadas) ValeCuatro = Just (m,j,turno,(env,jugE),re,(ValeCuatro,j),NoRespuesta,cartas,puntos,jugadas) -- ya se respondió el envido, puedo retrucar
cantarTruco (m,j,turno,(env,jugE),re,(Retruco,jugT),res,cartas,puntos,jugadas) _ = Nothing
--
cantarTruco (m,j,turno,(env,jugE),re,(ValeCuatro,jugT),res,cartas,puntos,jugadas) _ = Nothing -- no se puede cantar nada más que ValeCuatro


responderTruco :: Estado -> Respuesta -> Maybe Estado
responderTruco (m,j,turno,(env,jugE),re,(NoTruco,jugT),rt,cartas,puntos,jugadas) _ = Nothing -- si no me cantaron no puedo responder
responderTruco (m,j,t,(env,jugE),NoRespuesta,(Truco,jugT),rt,cartas,puntos,jugadas) res 
    | env == [] = Just (m,j,t,([],jugE),NoRespuesta,(Truco,jugT),res,cartas,puntos,jugadas) -- no hay envido colgado, puedo responder al truco
    | env /= [] = Nothing -- no puedo responder al truco si hay un envido colgado
responderTruco (m,j,turno,(env,jugE),re,(truco,jugT),rt,cartas,puntos,jugadas) NoRespuesta = Nothing
responderTruco (m,j,turno,(env,jugE),re,(truco,jugT),rt,cartas,puntos,jugadas) res = Just (m,j,turno,(env,jugE),re,(truco,jugT),res,cartas,puntos,jugadas)

------------------------------------------------------------

sumarPuntos :: Estado -> Estado

sumarPuntos (m,j,turno,([],jugE),re,(truco,jugT),Quiero,cartas,[p0,p1],jugadas)     -- si se quiso hay que ver quién ganó la mano
    |((ganaMano jugadas m) == Maquina) = (m,j,turno,([],jugE),re,(truco,jugT),Quiero,cartas,[p0+(sumarTruco truco Quiero),p1],jugadas)
    |otherwise                        = (m,j,turno,([],jugE),re,(truco,jugT),Quiero,cartas,[p0,p1+(sumarTruco truco Quiero)],jugadas)
--
sumarPuntos (m,j,turno,([],jugE),re,(truco,jugT),NoQuiero,cartas,[p0,p1],jugadas)   -- si no se quiso hay que ver quién cantó
    |(jugT == Maquina) = (m,j,turno,([],jugE),re,(truco,jugT),NoQuiero,cartas,[p0+(sumarTruco truco NoQuiero),p1],jugadas)
    |otherwise         = (m,j,turno,([],jugE),re,(truco,jugT),NoQuiero,cartas,[p0,p1+(sumarTruco truco NoQuiero)],jugadas)
--
sumarPuntos (m,j,turno,(env,jugE),Quiero,(truco,jugT),rt,[cartasM,cartasH],[p0,p1],[jugadasM,jugadasH]) -- si se quiso hay que ver quién gana
    |ganadorEnvido == Maquina = sumarPuntos (m,j,turno,([],jugE),Quiero,(truco,jugT),rt,[cartasM,cartasH],[p0+(sumarEnvido env Quiero p1),p1],[jugadasM,jugadasH])
    |otherwise                = sumarPuntos (m,j,turno,([],jugE),Quiero,(truco,jugT),rt,[cartasM,cartasH],[p0,p1+(sumarEnvido env Quiero p0)],[jugadasM,jugadasH])
        where
            ganadorEnvido = (ganaEnvido [(rearmarMano cartasM jugadasM),(rearmarMano cartasH jugadasH)] m)
--
sumarPuntos (m,j,turno,(env,jugE),NoQuiero,(truco,jugT),rt,cartas,[p0,p1],jugadas)  --si no se quiso hay que ver quién cantó
    |(jugE == Maquina) = sumarPuntos (m,j,turno,([],jugE),NoQuiero,(truco,jugT),rt,cartas,[p0+(sumarEnvido env NoQuiero p1),p1],jugadas)
    |otherwise         = sumarPuntos (m,j,turno,([],jugE),NoQuiero,(truco,jugT),rt,cartas,[p0,p1+(sumarEnvido env NoQuiero p0)],jugadas)

ganaEnvido :: [(Carta,Carta,Carta)] -> Jugador -> Jugador -- Toma las manos originales (rearmadas con la función rearmarMano) y el jugador que es mano. Devuelve el jugador que gana el Envido
ganaEnvido [(c11,c12,c13),(c21,c22,c23)] mano
    |envidoM > envidoH = Maquina
    |envidoM < envidoH = Humano
    |otherwise         = mano
        where
            envidoM = fromMaybe 0 (envido (c11,c12,c13))
            envidoH = fromMaybe 0 (envido (c21,c22,c23))

ganaMano :: [(Carta,Carta,Carta)] -> Jugador -> Jugador -- Revisa las cartas jugadas y dice quien ganó la mano. Si empardan las 3 gana el mano
ganaMano [(m1,m2,m3),(h1,h2,h3)] mano
    | (m1 > h1) && (m2 > h2) = Maquina
    | (m1 == h1) && (m2 > h2) = Maquina
    | (m1 > h1) && (m3 > h3) = Maquina
    | (m1 == h1) && (m2 == h2) && (m3 > h3) = Maquina
    | (m1 > h1) && (m2 < h2) && (m3 == h3) = Maquina
    | (m2 > h2) && (m3 > h3) = Maquina
    | (m1 == h1) && (m2 == h2) && (m3 == h3) = mano
    | otherwise = Humano

sumarEnvido :: [Envido] -> Respuesta -> Int -> Int -- Envidos cantados, Respuesta al ultimo envido, puntos que tiene el otro jugador (para la falta)
sumarEnvido [] re _ = 0
sumarEnvido [e] NoQuiero _ = 1
sumarEnvido (e:xe) NoQuiero p = sumarEnvido xe Quiero p
sumarEnvido (Envido:xe) Quiero p
    | xe == [] = 2
    | xe /= [] = if (last xe == FaltaEnvido) then (30-p) else (2 + sumarEnvido xe Quiero p)
sumarEnvido (RealEnvido:xe) Quiero p
    | xe == [] = 3
    | xe /= [] = if (last xe == FaltaEnvido) then (30-p) else (3 + sumarEnvido xe Quiero p)
sumarEnvido (FaltaEnvido:xe) Quiero p = (30 - p)

sumarTruco :: Truco -> Respuesta -> Int
sumarTruco Truco Quiero = 2
sumarTruco Retruco Quiero = 3
sumarTruco ValeCuatro Quiero = 4
sumarTruco truco NoQuiero = sumarTruco truco Quiero - 1
sumarTruco NoTruco _ = 1

-----------------------------------------------------------------

jugarCarta :: Estado -> Int -> Jugador -> Maybe Estado -- Estado antes de jugar -> carta a jugar (1,2 ó 3) -> quién está jugando
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[(CartaNula,c2,c3),cartasH],puntos,[(j1,j2,j3),jugadasH]) 1 Maquina = Nothing
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,c3),cartasH],puntos,[(j1,j2,j3),jugadasH]) 1 Maquina
    | j1 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(CartaNula,c2,c3),cartasH],puntos,[(c1,CartaNula,CartaNula),jugadasH])
    | j2 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(CartaNula,c2,c3),cartasH],puntos,[(j1,c1,CartaNula),jugadasH])
    | j3 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(CartaNula,c2,c3),cartasH],puntos,[(j1,j2,c1),jugadasH])
    | otherwise = Nothing
    --
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,CartaNula,c3),cartasH],puntos,[(j1,j2,j3),jugadasH]) 2 Maquina = Nothing
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,c3),cartasH],puntos,[(j1,j2,j3),jugadasH]) 2 Maquina
    | j1 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,CartaNula,c3),cartasH],puntos,[(c2,CartaNula,CartaNula),jugadasH])
    | j2 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,CartaNula,c3),cartasH],puntos,[(j1,c2,CartaNula),jugadasH])
    | j3 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,CartaNula),cartasH],puntos,[(j1,j2,c2),jugadasH])
    | otherwise = Nothing
--
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,CartaNula,c3),cartasH],puntos,[(j1,j2,j3),jugadasH]) 3 Maquina = Nothing
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,c3),cartasH],puntos,[(j1,j2,j3),jugadasH]) 3 Maquina
    | j1 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,CartaNula),cartasH],puntos,[(c3,CartaNula,CartaNula),jugadasH])
    | j2 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,CartaNula),cartasH],puntos,[(j1,c3,CartaNula),jugadasH])
    | j3 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[(c1,c2,CartaNula),cartasH],puntos,[(j1,j2,c3),jugadasH])
    | otherwise = Nothing
--
--
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(CartaNula,c2,c3)],puntos,[jugadasM,(j1,j2,j3)]) 1 Humano = Nothing
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,c3)],puntos,[jugadasM,(j1,j2,j3)]) 1 Humano
    | j1 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(CartaNula,c2,c3)],puntos,[jugadasM,(c1,CartaNula,CartaNula)])
    | j2 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(CartaNula,c2,c3)],puntos,[jugadasM,(j1,c1,CartaNula)])
    | j3 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(CartaNula,c2,c3)],puntos,[jugadasM,(j1,j2,c1)])
    | otherwise = Nothing
    --
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,CartaNula,c3)],puntos,[jugadasM,(j1,j2,j3)]) 2 Humano = Nothing
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,c3)],puntos,[jugadasM,(j1,j2,j3)]) 2 Humano
    | j1 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,CartaNula,c3)],puntos,[jugadasM,(c2,CartaNula,CartaNula)])
    | j2 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,CartaNula,c3)],puntos,[jugadasM,(j1,c2,CartaNula)])
    | j3 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,CartaNula)],puntos,[jugadasM,(j1,j2,c2)])
    | otherwise = Nothing
--
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,CartaNula,c3)],puntos,[jugadasM,(j1,j2,j3)]) 3 Humano = Nothing
jugarCarta (m,j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,c3)],puntos,[jugadasM,(j1,j2,j3)]) 3 Humano
    | j1 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,CartaNula)],puntos,[jugadasM,(c3,CartaNula,CartaNula)])
    | j2 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,CartaNula)],puntos,[jugadasM,(j1,c3,CartaNula)])
    | j3 == CartaNula = Just (m,cambioJugador j,turno,(env,jugE),re,(truco,jugT),rt,[cartasM,(c1,c2,CartaNula)],puntos,[jugadasM,(j1,j2,c3)])
    | otherwise = Nothing
    
-----------------------------------------------------------------------------

aumentarTurno :: Estado -> Estado
aumentarTurno (m,j,turno,(env,jugE),re,(truco,jugT),rt,cartas,puntos,[(m1,m2,m3),(h1,h2,h3)])
    | m1 > h1   = (m,Maquina,turno+1,(env,jugE),re,(truco,jugT),rt,cartas,puntos,[(m1,m2,m3),(h1,h2,h3)])
    | otherwise = (m,Humano,turno+1,(env,jugE),re,(truco,jugT),rt,cartas,puntos,[(m1,m2,m3),(h1,h2,h3)])
